home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 5 / QRZ Ham Radio Callsign Database - Volume 5.iso / files / tcpip / amiga / asrc29p.lha / pppipcp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-29  |  41.8 KB  |  1,736 lines

  1. /*
  2.  *  PPPIPCP.C    -- negotiate IP parameters
  3.  *
  4.  *    12-89    -- Katie Stevens (dkstevens@ucdavis.edu)
  5.  *           UC Davis, Computing Services
  6.  *    PPP.04    02-90    [ks] make automatic route entry a private route
  7.  *    PPP.07    04-90    [ks] make IP addr negotiation independent of
  8.  *                 whether host is active or passive open
  9.  *                 thanks to Brad Clements, bkc@omnigate.clarkson.edu
  10.  *                 dont bring up IP unless both addrs are known
  11.  *    PPP.08    05-90    [ks] IP compr: we request means we want to rcv compr;
  12.  *                 remote requests means we should xmt compr TCP.
  13.  *                 improve PPP trace reporting
  14.  *    PPP.09    05-90    [ks] add UPAP auth protocol
  15.  *    PPP.10    07-90    [ks] make ppp open/close/reset work properly
  16.  *                 add peerID-to-IPaddr lookup table
  17.  *                 add peer IP lookup pool
  18.  *    PPP.13    08-90    [ks] add timestamp on PPP link open
  19.  *    PPP.14    08-90    [ks] change UPAP to PAP for consistency with RFC1172
  20.  *                 make IPCP timeout configurable
  21.  *    PPP.15    09-90    [ks] update to KA9Q NOS v900828
  22.  */
  23.  
  24. #include <stdio.h>
  25. #include <ctype.h>
  26. #include <time.h>
  27. #include "global.h"
  28. #include "files.h"
  29. #include "netuser.h"
  30. #include "mbuf.h"
  31. #include "proc.h"
  32. #include "iface.h"
  33. #include "ip.h"
  34. #include "tcp.h"
  35. #include "slcompre.h"
  36. #include "ppp.h"
  37. #include "slip.h"
  38.  
  39. extern int32 Ip_addr;
  40.  
  41. /* Counter for PPP id field */
  42. extern unsigned char pppid;
  43.  
  44. /* PPP tracing */
  45. extern int ppptrace;
  46.  
  47. static void ipcp_open __ARGS((struct slip *sp));
  48. static int ipcp_addr_idle __ARGS((int32 addr));
  49. static int32 ipcp_lookuppeer __ARGS((char *peerid));
  50. static int32 ipcp_poolnext __ARGS((struct ipcppool *poolp));
  51. static void ipcp_reset_tcp __ARGS((struct slip *sp));
  52.  
  53. static int ipcp_sendreq __ARGS((struct slip *sp));
  54. static struct mbuf *ipcp_makereq __ARGS((struct ipcpctl *ipcpiop));
  55.  
  56. static void ipcp_rcvack __ARGS((struct slip *sp, struct cnfhdr *rcnf,
  57.             struct mbuf *data));
  58. static void ipcp_rcvnak __ARGS((struct slip *sp, struct cnfhdr *rcnf,
  59.             struct mbuf *data));
  60. static void ipcp_rcvrej __ARGS((struct slip *sp, struct cnfhdr *rcnf,
  61.             struct mbuf *data));
  62. static void ipcp_rcvreq __ARGS((struct slip *sp, struct cnfhdr *rcnf,
  63.             struct mbuf *data));
  64. static void ipcp_rcvtermack __ARGS((struct slip *sp));
  65. static void ipcp_rcvtermreq __ARGS((struct slip *sp, struct cnfhdr *rcnf));
  66. static void ipcp_shutdown __ARGS((struct slip *sp));
  67.  
  68. static int ipcp_chkack __ARGS((struct slip *sp, struct cnfhdr *ackcnf,
  69.             struct mbuf *data));
  70. static int ipcp_chknak __ARGS((struct slip *sp, struct cnfhdr *nakcnf,
  71.             struct mbuf *data));
  72. static int ipcp_chkrej __ARGS((struct slip *sp, struct cnfhdr *rejcnf,
  73.             struct mbuf *data));
  74. static void ipcp_chkreq __ARGS((struct slip *sp, struct cnfhdr *reqcnf,
  75.             struct mbuf *data));
  76.  
  77. static void ipcp_timeout __ARGS((void *vp));
  78. static void ipcp_timer __ARGS((struct slip *sp));
  79.  
  80. static int ipcp_sendreply __ARGS((struct slip *sp, char code,
  81.             unsigned char id, struct mbuf *data));
  82.  
  83. /* In PPPLCP.C */
  84. /* Possible IPCP states same as possible LCP states */
  85. extern char *LCPStates[];
  86. extern char *LCPCodes[];
  87.  
  88. static char BVJ[] = "    Begin Van Jacobson TCP/IP header compression (%s) on %s packets";
  89.  
  90. /****************************************************************************/
  91.  
  92. /* Initialize IP Control Protocol state machine for config exchange */
  93. int
  94. ipcp_start(sp)
  95. struct slip *sp;
  96. {
  97.     struct pppctl *pppiop;
  98.     struct lcpctl *lcpiop;
  99.     struct ipcpctl *ipcpiop;
  100.  
  101.     if (ppptrace > 5)
  102.         mainlog(-1, "ipcp_start()");
  103.  
  104.     pppiop = sp->pppio;
  105.     lcpiop = &(pppiop->lcpio);
  106.     ipcpiop = &(pppiop->ipcpio);
  107.  
  108.     /* Just finished LCP negotiation; prepare for IPCP negotiation */
  109.     pppiop->state = PPP_IPCP;
  110.     ipcp_reset(sp);
  111.     /* Can set peer_addr with 'ppp peer' command */
  112.     ipcpiop->attempt_dest = ipcpiop->peer_addr;
  113.     /* If not already set, can lookup PAP peer ID in PPPHOSTS file */
  114.     if ((ipcpiop->peer_addr == 0L) &&
  115.         (lcpiop->lclparm.auth_type == PAP_AUTH_TYPE)) {
  116.         ipcpiop->attempt_dest = ipcp_lookuppeer(lcpiop->pap_user);
  117.     }
  118.     /* If still not set, can get next address from PPP pool */
  119.     if ((ipcpiop->peer_addr == 0L) &&
  120.         (ipcpiop->peer_pool != NULLPOOL)) {
  121.         ipcpiop->attempt_dest = ipcp_poolnext(ipcpiop->peer_pool);
  122.     }
  123.     if (ipcpiop->attempt_dest == 0L)
  124.         ipcpiop->accept_addrs = 1;
  125.  
  126.     if (!ipcpiop->active) {
  127.         /* Passive open; wait until remote host attempts connection */
  128.         ipcpiop->ipcp_state = IPCP_LISTEN;
  129.         return 0;
  130.     }
  131.  
  132.     /* Active open; begin IPCP configuration negotiation */
  133.     ipcpiop->ipcp_state = IPCP_CLOSED;    
  134.     return(ipcp_sendreq(sp));
  135. }
  136.  
  137. /*******************************************/
  138.  
  139. /* Close the IP connection from local side */
  140. int
  141. ipcp_close(sp)
  142. struct slip *sp;
  143. {
  144.     struct pppctl *pppiop;
  145.     struct ipcpctl *ipcpiop;
  146.  
  147.     if (ppptrace > 5)
  148.         mainlog(-1,"ipcp_close()");
  149.  
  150.     pppiop = sp->pppio;
  151.     ipcpiop = &(pppiop->ipcpio);
  152.     if ((ipcpiop->ipcp_state == IPCP_CLOSED) ||
  153.         (ipcpiop->ipcp_state == IPCP_LISTEN))   {
  154.         /* Already closed */
  155.         return 0;
  156.     }
  157.  
  158.     if (ppptrace > 1)
  159.         mainlog(-1,"%s: PPP/IPCP IP Closing",sp->iface->name);
  160.  
  161.     /* Reset IP connections on this interface */
  162.     ipcp_reset_tcp(sp);
  163.     /* Remove routing entry from route table */
  164.     rt_drop(ipcpiop->attempt_dest, (unsigned int)32);
  165.  
  166.     /* Set a timer against our request to shutdown */
  167.     ipcp_timer(sp);
  168.     /* Ask remote host to shutdown */
  169.     ipcpiop->ipcp_state = IPCP_TERMINATE;
  170.     ipcpiop->ack_retry = 0;
  171.     if (ipcp_sendreply(sp, TERMINATE_REQ, 0, NULLBUF) == 0)
  172.         pwait(ipcpiop);
  173.     return 0;
  174. }
  175.  
  176. /* Initialize our IPCP configuration options to compiled default options */
  177. void
  178. ipcp_init(sp)
  179. struct slip *sp;
  180. {
  181.     struct pppctl *pppiop;
  182.     struct ipcpctl *ipcpiop;
  183.     struct timer *t;
  184.  
  185.     if (ppptrace > 5)
  186.         mainlog(-1, "ipcp_init()");
  187.  
  188.     pppiop = sp->pppio;
  189.     ipcpiop = &(pppiop->ipcpio);
  190.     t = &(ipcpiop->ipcp_tm);
  191.     ipcpiop->ipcp_state = IPCP_CLOSED;
  192.  
  193.     /* Set option parameters to first request defaults */
  194.     ipcpiop->peer_addr = 0L;
  195.     ipcpiop->neg_ip_compr = 0;
  196.     ipcpiop->ip_compr_type = DEF_IP_COMPR;
  197.     /* Initialize timer */
  198.     t->start = IPCP_TIMEOUT*(1000L/MSPTICK);
  199.     ipcp_timer(sp);
  200.     stop_timer(&(ipcpiop->ipcp_tm));
  201.  
  202.     ipcp_reset(sp);
  203.     return;
  204. }
  205.  
  206. /* IP Control configuration negotiation complete */
  207. static void
  208. ipcp_open(sp)
  209. struct slip *sp;
  210. {
  211.     struct pppctl *pppiop;
  212.     struct ipcpctl *ipcpiop;
  213.  
  214.     pppiop = sp->pppio;
  215.     ipcpiop = &(pppiop->ipcpio);
  216.  
  217.     /* Mark IPCP layer as open */
  218.     if (ppptrace)
  219.         mainlog(-1,"%s: PPP/IPCP IP Open",sp->iface->name);
  220.     ipcpiop->ipcp_state = IPCP_OPEN;
  221.  
  222.     /* Make sure we found out IP address at each end */
  223.     if ((ipcpiop->attempt_src != ipcpiop->accept_dest)
  224.         || (ipcpiop->attempt_src == 0L)) {
  225.         if (ppptrace)
  226.             mainlog(-1,"Couldnt negotiate local IP addr for interface %s",
  227.                 sp->iface->name);
  228.         ipcp_shutdown(sp);
  229.         return;
  230.     }
  231.     if ((ipcpiop->attempt_dest != ipcpiop->accept_src)
  232.         || (ipcpiop->attempt_dest == 0L)) {
  233.         if (ppptrace)
  234.             mainlog(-1,"Couldnt negotiate remote peer IP addr for interface %s",
  235.                 sp->iface->name);
  236.         ipcp_shutdown(sp);
  237.         return;
  238.     }
  239.  
  240.     /* Set IP compression to reflect negotiated option */
  241.     switch (ipcpiop->lcl_ip_compr) {
  242.     case IPCP_OVJCOMP:
  243.         sp->escaped |= PPP_RCV_VJCOMPR;
  244.         if (ppptrace > 1)
  245.             mainlog(-1,BVJ, "OLD", "incoming");
  246.         break;
  247.     case IPCP_NVJCOMP:
  248.         sp->escaped |= PPP_RCV_VJCOMPR;
  249.         if (ppptrace > 1)
  250.             mainlog(-1,BVJ, "NEW", "incoming");
  251.         break;
  252.     default:
  253.         sp->escaped &= ~PPP_RCV_VJCOMPR;
  254.     }
  255.     switch (ipcpiop->rem_ip_compr) {
  256.     case IPCP_OVJCOMP:
  257.         sp->escaped |= PPP_XMT_VJCOMPR;
  258.         if (ppptrace > 1)
  259.             mainlog(-1,BVJ, "OLD", "outgoing");
  260.         break;
  261.     case IPCP_NVJCOMP:
  262.         sp->escaped |= PPP_XMT_VJCOMPR;
  263.         if (ppptrace > 1)
  264.             mainlog(-1,BVJ, "NEW", "outgoing");
  265.         break;
  266.     default:
  267.         sp->escaped &= ~PPP_XMT_VJCOMPR;
  268.     }
  269.     if ((sp->escaped & (PPP_RCV_VJCOMPR | PPP_XMT_VJCOMPR)) != 0) {
  270.         /* Initialize compression control structure */
  271.         sp->slcomp = (struct slcompress *)mallocw(sizeof(struct slcompress));
  272.         sl_compress_init(sp->slcomp);
  273.     }
  274.  
  275.     /* Set our IP address to reflect negotiated option */
  276.     if (ipcpiop->attempt_src != sp->iface->addr) {
  277.         if (Ip_addr == 0L)
  278.             Ip_addr = ipcpiop->attempt_src;
  279.         sp->iface->addr = ipcpiop->attempt_src;
  280.         if (ppptrace > 1)
  281.             mainlog(-1,"    Saving new IP addr for interface %s: %s",
  282.                 sp->iface->name,inet_ntoa(sp->iface->addr));
  283.     }
  284.  
  285.     /* Add point-to-point route to remote PPP host */
  286.     rt_add(ipcpiop->attempt_dest, (unsigned int)32, (int32)0,
  287.         sp->iface, (int32)1, (int32)0, (char)1);
  288.     if (ppptrace > 1)
  289.         mainlog(-1,"    Add route to peer (%s) on interface %s",
  290.             inet_ntoa(ipcpiop->attempt_dest),
  291.             sp->iface->name);
  292.  
  293. /* Allow any queued IP traffic */
  294.     pppiop->state = PPP_OPEN;
  295.     pppiop->upsince = time(0L);
  296.     return;
  297. }
  298.  
  299. /* Reset IPCP configuration options for initial request */
  300. int
  301. ipcp_reset(sp)
  302. struct slip *sp;
  303. {
  304.     struct pppctl *pppiop;
  305.     struct ipcpctl *ipcpiop;
  306.  
  307.     if (ppptrace > 5)
  308.         mainlog(-1, "ipcp_reset()");
  309.  
  310.     pppiop = sp->pppio;
  311.     ipcpiop = &(pppiop->ipcpio);
  312.     ipcpiop->ipcp_state = IPCP_CLOSED;
  313.     ipcpiop->ack_retry = 0;
  314.     ipcpiop->active = pppiop->lcpio.active;
  315.  
  316.     /* Set up for IP addr exchange; attempt values set in ipcp_start() */
  317.     ipcpiop->attempt_addrs = 1;
  318.     ipcpiop->attempt_src = Ip_addr;
  319.     /* If we dont know our IP address, or if we dont know IP addr */
  320.     /* of the remote host, accept address assignment from remote  */
  321.     if ((ipcpiop->attempt_src == 0L)||(ipcpiop->attempt_dest == 0L)) {
  322.         ipcpiop->accept_addrs = 1;
  323.     } else {
  324.         ipcpiop->accept_addrs = 0;
  325.     }
  326.     ipcpiop->accept_src = ipcpiop->attempt_dest;
  327.     ipcpiop->accept_dest = ipcpiop->attempt_src;
  328.  
  329.     /* Reset IP header compression options to first request defaults */
  330.     ipcpiop->attempt_ip_compr = ipcpiop->neg_ip_compr;
  331.     ipcpiop->lcl_ip_compr = ipcpiop->ip_compr_type;
  332.     ipcpiop->accept_ip_compr = 1;
  333.     ipcpiop->rem_ip_compr = DEF_IP_COMPR;
  334.     sp->escaped &= ~PPP_RCV_VJCOMPR;
  335.     sp->escaped &= ~PPP_XMT_VJCOMPR;
  336.  
  337.     return 0;
  338. }
  339.  
  340. /*******************************************/
  341.  
  342. static int
  343. ipcp_addr_idle(addr)
  344. int32 addr;
  345. {
  346.     struct iface *ifp;
  347.     struct pppctl *pppiop;
  348.  
  349.     /* Check if peer IP address is already in use on another interface */
  350.     for (ifp=Ifaces; ifp != NULLIF; ifp = ifp->next) {
  351.         if ((Slip[ifp->xdev].iface == ifp) &&
  352.             (Slip[ifp->xdev].type == TYPE_PPP)) {
  353.             pppiop = Slip[ifp->xdev].pppio;
  354.             if ((pppiop->ipcpio.ipcp_state != IPCP_CLOSED) &&
  355.                 (pppiop->ipcpio.attempt_dest == addr))        {
  356.                 return 0;
  357.             }
  358.         }
  359.     }
  360.     return 1;
  361. }
  362.  
  363. /* Check if we have a specific IP address to assign to remote peer host */
  364. static int32
  365. ipcp_lookuppeer(peerid)
  366. char *peerid;
  367. {
  368.     FILE *peerfp;
  369.     char buf[128];
  370.     char *cp;
  371.     int32 peer_addr = 0L;
  372.  
  373.     if ((peerfp = fopen(Userfile, READ_TEXT)) == NULLFILE)
  374.         return 0L;
  375.     while (fgets(buf,128,peerfp) != NULLCHAR) {
  376.         if(buf[0] == '#')
  377.             continue;    /* Comment */
  378.         if((cp = strchr(buf,' ')) == NULLCHAR)
  379.             /* Bogus entry */
  380.             continue;
  381.         *cp++ = '\0';        /* Now points to password */
  382.         if(stricmp(peerid,buf) == 0) {
  383.             ++cp;
  384.             if ((cp = strrchr(cp,' ')) == NULLCHAR)
  385.                 /* No IP address given */
  386.                 break;
  387.             ++cp;
  388.             peer_addr = resolve(cp);
  389.             break;        /* Found user name */
  390.         }
  391.     }
  392.     fclose(peerfp);
  393.     return(peer_addr);
  394. }
  395.  
  396. static int32
  397. ipcp_poolnext(poolp)
  398. struct ipcppool *poolp;
  399. {
  400.     int i;
  401.     int32 nextaddr = 0L;
  402.  
  403.     for (i=0; i<=(poolp->peer_max - poolp->peer_min); ++i) {
  404.         if (ipcp_addr_idle(poolp->peer_next))
  405.             nextaddr = poolp->peer_next;
  406.  
  407.         if (poolp->peer_next == poolp->peer_max)
  408.             poolp->peer_next = poolp->peer_min;
  409.         else
  410.             ++poolp->peer_next;
  411.  
  412.         if (nextaddr != 0L)
  413.             break;
  414.     }
  415.     return(nextaddr);
  416. }
  417.  
  418. /* Close all TCP connections in preparation for PPP link shutdown */
  419. static void
  420. ipcp_reset_tcp(sp)
  421. struct slip *sp;
  422. {
  423.     register struct iface *ifp;
  424.     register int i;
  425.     register struct tcb *tcb;
  426.     register struct route *rp;
  427.  
  428.     ifp = sp->iface;
  429.  
  430.     for(i=0;i<NTCB;i++){
  431.         for(tcb=Tcbs[i];tcb != NULLTCB;tcb = tcb->next) {
  432.             if ((tcb->state == TCP_LISTEN) &&
  433.                 (tcb->flags.clone == 1))      {
  434.                 /* Leave servers alone */
  435.                 continue;
  436.             }
  437.             rp = rt_lookup(tcb->conn.remote.address);
  438.             if (rp->iface == ifp) {
  439.                 /* Reset active connections */
  440.                 reset_tcp(tcb);
  441.             }
  442.         }
  443.     }
  444.     /* Wait 1sec for any replys or static */
  445.     pause( (1L*1000) / MSPTICK );
  446.     return;
  447. }
  448.  
  449. /****************************************************************************/
  450.  
  451. /* Send our IPCP configuration request */
  452. static int
  453. ipcp_sendreq(sp)
  454. struct slip *sp;
  455. {
  456.     struct pppctl *pppiop;
  457.     struct ipcpctl *ipcpiop;
  458.     struct mbuf *bp;
  459.  
  460.     if (ppptrace > 5)
  461.         mainlog(-1,"ipcp_sendreq()");
  462.  
  463.     pppiop = sp->pppio;
  464.     ipcpiop = &(pppiop->ipcpio);
  465.  
  466.     /* Get a packet with our configuration request */
  467.     bp = ipcp_makereq(ipcpiop);
  468.  
  469.     /* Start timer against wait for reply to our config request */
  470.     ipcp_timer(sp);
  471.  
  472.     /* Send IPCP configuration request to remote host */
  473.     pppiop->state = PPP_IPCP;
  474.     if (ipcpiop->ipcp_state != IPCP_ACK_SENT)
  475.         ipcpiop->ipcp_state = IPCP_REQ_SENT;
  476.     return(ipcp_sendreply(sp, CONFIG_REQ, 0, bp));
  477. }
  478.  
  479. /*******************************************/
  480.  
  481. static struct mbuf *
  482. ipcp_makereq(ipcpiop)
  483. struct ipcpctl *ipcpiop;
  484. {
  485.     register unsigned char *cp;
  486.     struct mbuf *bp;
  487.     struct mbuf *req_bp = NULLBUF;
  488.  
  489.     if (ppptrace > 5)
  490.         mainlog(-1,"    ipcp_makereq()");
  491.  
  492.     /* Request our preferred IP control options */
  493.     if (ipcpiop->attempt_addrs) {
  494.         /* Attempt to negotiate IP addrs */
  495.         if (ppptrace > 5) {
  496.             mainlog(-1,"    asking for src addr: %s",
  497.                 inet_ntoa(ipcpiop->attempt_src));
  498.             mainlog(-1,"    asking for dest addr: %s",
  499.                 inet_ntoa(ipcpiop->attempt_dest));
  500.         }
  501.         if ((bp = alloc_mbuf(10)) == NULLBUF)
  502.             return NULLBUF;
  503.         cp = bp->data;
  504.         *cp++ = IP_ADDRS;
  505.         *cp++ = 10;
  506.         cp = put32(cp, ipcpiop->attempt_src);
  507.         put32(cp, ipcpiop->attempt_dest);
  508.         bp->cnt += 10;
  509.         append(&req_bp, bp);
  510.     }
  511.  
  512.     /* IP header compression */
  513.     if (ipcpiop->attempt_ip_compr) {
  514.         if (ppptrace > 5) {
  515.             mainlog(-1,"    asking for IP compression: %x",
  516.                 ipcpiop->lcl_ip_compr);
  517.         }
  518.  
  519.         /* Attempt to negotiate IP compression */
  520.         if ((bp = alloc_mbuf(4)) == NULLBUF)
  521.             return NULLBUF;
  522.         cp = bp->data;
  523.         *cp++ = IP_COMPR_TYPE;
  524.         *cp++ = 4;
  525.         put16(cp, ipcpiop->lcl_ip_compr);
  526.         bp->cnt += 4;
  527.         append(&req_bp, bp);
  528.     }
  529.  
  530.     /* Return our config request */
  531.     return(req_bp);
  532. }
  533.  
  534. /****************************************************************************/
  535.  
  536. /* Remote host ACKed our configuration request */
  537. static void
  538. ipcp_rcvack(sp, rcnf, data)
  539. struct slip *sp;
  540. struct cnfhdr *rcnf;
  541. struct mbuf *data;
  542. {
  543.     struct pppctl *pppiop;
  544.     struct ipcpctl *ipcpiop;
  545.  
  546.     if (ppptrace > 5)
  547.         mainlog(-1, "ipcp_rcvack()");
  548.  
  549.     pppiop = sp->pppio;
  550.     ipcpiop = &(pppiop->ipcpio);
  551.     stop_timer(&ipcpiop->ipcp_tm);
  552.  
  553.     switch(ipcpiop->ipcp_state) {
  554.     case IPCP_REQ_SENT:
  555.         /* Make sure ACK is proper */
  556.         if (ipcp_chkack(sp, rcnf, data) != -1) {
  557.             /* Remote host accepted our request */
  558.             ipcpiop->ipcp_state = IPCP_ACK_RCVD;
  559.         }
  560.  
  561.         /* Still need to settle request from remote host */
  562.         ipcp_timer(sp);
  563.         break;
  564.  
  565.     case IPCP_ACK_SENT:
  566.         /* Make sure ACK is proper */
  567.         if (ipcp_chkack(sp, rcnf, data) == -1) {
  568.             /* Error in ACK from remote host */
  569.             /* Wait for another ACK, then send another request */
  570.             ipcp_timer(sp);
  571.         } else {
  572.             /* IPCP negotiation complete */
  573.             ipcp_open(sp);
  574.         }
  575.         break;
  576.  
  577.     case IPCP_ACK_RCVD:
  578.     case IPCP_OPEN:
  579.         /* Something went wrong; restart negotiations */
  580.         free_p(data);    
  581.         ipcp_reset(sp);
  582.         ipcp_sendreq(sp);
  583.         break;
  584.     case IPCP_TERMINATE:
  585.         /* We are attempting to close connection; wait */
  586.         /* for timeout to resend a Terminate Request */
  587.         free_p(data);
  588.         break;
  589.     case IPCP_CLOSED:
  590.     case IPCP_LISTEN:
  591.     default:
  592.         /* Confusion; shutdown the connection */
  593.         free_p(data);
  594.         ipcp_shutdown(sp);
  595.         break;
  596.     }
  597.     return;
  598. }
  599.  
  600. /* Remote host NAKed our configuration request */
  601. static void
  602. ipcp_rcvnak(sp, rcnf, data)
  603. struct slip *sp;
  604. struct cnfhdr *rcnf;
  605. struct mbuf *data;
  606. {
  607.     struct pppctl *pppiop;
  608.     struct ipcpctl *ipcpiop;
  609.  
  610.     if (ppptrace > 5)
  611.         mainlog(-1, "ipcp_rcvnak()");
  612.  
  613.     pppiop = sp->pppio;
  614.     ipcpiop = &(pppiop->ipcpio);
  615.     stop_timer(&ipcpiop->ipcp_tm);
  616.  
  617.     switch(ipcpiop->ipcp_state) {
  618.     case IPCP_REQ_SENT:
  619.     case IPCP_ACK_SENT:
  620.         /* Update our config request to reflect NAKed options */
  621.         if (ipcp_chknak(sp, rcnf, data) == -1) {
  622.             /* Bad NAK packet */
  623.             /* Wait for another; resend request on timeout */
  624.             ipcp_timer(sp);
  625.         } else {
  626.             /* Send updated config request */
  627.             ipcp_sendreq(sp);
  628.         }
  629.         break;
  630.  
  631.     case IPCP_ACK_RCVD:
  632.     case IPCP_OPEN:
  633.         /* Something went wrong; restart negotiations */
  634.         free_p(data);    
  635.         ipcp_reset(sp);
  636.         ipcp_sendreq(sp);
  637.         break;
  638.     case IPCP_TERMINATE:
  639.         /* We are attempting to close connection; wait */
  640.         /* for timeout to resend a Terminate Request */
  641.         free_p(data);
  642.         break;
  643.     case IPCP_CLOSED:
  644.     case IPCP_LISTEN:
  645.     default:
  646.         /* Confusion; shutdown the connection */
  647.         free_p(data);
  648.         ipcp_shutdown(sp);
  649.         break;
  650.     }
  651.     return;
  652. }
  653.  
  654. /* Remote host rejected our configuration request */
  655. static void
  656. ipcp_rcvrej(sp, rcnf, data)
  657. struct slip *sp;
  658. struct cnfhdr *rcnf;
  659. struct mbuf *data;
  660. {
  661.     struct pppctl *pppiop;
  662.     struct ipcpctl *ipcpiop;
  663.  
  664.     if (ppptrace > 5)
  665.         mainlog(-1, "ipcp_rcvrej()");
  666.  
  667.     pppiop = sp->pppio;
  668.     ipcpiop = &(pppiop->ipcpio);
  669.     stop_timer(&ipcpiop->ipcp_tm);
  670.  
  671.     switch(ipcpiop->ipcp_state) {
  672.     case IPCP_REQ_SENT:
  673.     case IPCP_ACK_SENT:
  674.         /* Update our config request to reflect rejected options */
  675.         if (ipcp_chkrej(sp, rcnf, data) == -1) {
  676.             /* Bad reject packet */
  677.             /* Wait for another; resend request on timeout */
  678.             ipcp_timer(sp);
  679.         } else {
  680.             /* Send updated config request */
  681.             ipcp_sendreq(sp);
  682.         }
  683.         break;
  684.  
  685.     case IPCP_ACK_RCVD:
  686.     case IPCP_OPEN:
  687.         /* Something went wrong; restart negotiations */
  688.         free_p(data);    
  689.         ipcp_reset(sp);
  690.         ipcp_sendreq(sp);
  691.         break;
  692.     case IPCP_TERMINATE:
  693.         /* We are attempting to close connection; wait */
  694.         /* for timeout to resend a Terminate Request */
  695.         free_p(data);
  696.         break;
  697.     case IPCP_CLOSED:
  698.     case IPCP_LISTEN:
  699.     default:
  700.         /* Confusion; shutdown the connection */
  701.         free_p(data);
  702.         ipcp_shutdown(sp);
  703.         break;
  704.     }
  705.     return;
  706. }
  707.  
  708. /* Process configuration request sent by remote host */
  709. static void
  710. ipcp_rcvreq(sp, rcnf, data)
  711. struct slip *sp;
  712. struct cnfhdr *rcnf;
  713. struct mbuf *data;
  714. {
  715.     struct pppctl *pppiop;
  716.     struct ipcpctl *ipcpiop;
  717.  
  718.     if (ppptrace > 5)
  719.         mainlog(-1, "ipcp_rcvreq()");
  720.  
  721.     pppiop = sp->pppio;
  722.     ipcpiop = &(pppiop->ipcpio);
  723.  
  724.     switch(ipcpiop->ipcp_state) {
  725.     case IPCP_LISTEN:    /* Normal event */
  726.     case IPCP_ACK_SENT:    /* Unexpected event */
  727.     case IPCP_OPEN:        /* Unexpected event */
  728.         /* Reset IPCP state machine for configuration negotiation */
  729.         ipcp_reset(sp);
  730.         /* Send our configuration request */    
  731.         ipcp_sendreq(sp);
  732.         /* Evaluate configuration request from remote host */
  733.         ipcp_chkreq(sp, rcnf, data);
  734.         break;
  735.  
  736.     case IPCP_ACK_RCVD:
  737.         /* Stop timer against wait for config request */
  738.         stop_timer(&(ipcpiop->ipcp_tm));
  739.     case IPCP_REQ_SENT:
  740.         /* Evaluate configuration request from remote host */
  741.         ipcp_chkreq(sp, rcnf, data);
  742.         break;
  743.  
  744.     case IPCP_TERMINATE:
  745.         /* We are attempting to close connection; wait */
  746.         /* for timeout to resend a Terminate Request   */
  747.         free_p(data);
  748.         break;
  749.  
  750.     case IPCP_CLOSED:
  751.     default:
  752.         /* We are closed; dont accept any connections */
  753.         free_p(data);
  754.         ipcp_shutdown(sp);
  755.         break;
  756.     }
  757.     return;
  758. }
  759.  
  760. /* Remote host closed connection */
  761. static void
  762. ipcp_rcvtermack(sp)
  763. struct slip *sp;
  764. {
  765.     struct pppctl *pppiop;
  766.     struct ipcpctl *ipcpiop;
  767.  
  768.     if (ppptrace > 5)
  769.         mainlog(-1,"ipcp_rcvtermack()");
  770.  
  771.     pppiop = sp->pppio;
  772.     ipcpiop = &(pppiop->ipcpio);
  773.     stop_timer(&(ipcpiop->ipcp_tm));
  774.  
  775.     switch(ipcpiop->ipcp_state) {
  776.     case IPCP_OPEN:
  777.         /* Remote host has abruptly closed connection */
  778.         /* Reset IP connections on this interface */
  779.         ipcp_reset_tcp(sp);
  780.         /* Remove routing entry from route table */
  781.         rt_drop(ipcpiop->attempt_dest, (unsigned int)32);
  782.         /* Fall through */
  783.     case IPCP_TERMINATE:
  784.         /* Remote host has responded to our terminate request */
  785.         if (ppptrace)
  786.             mainlog(-1,"%s: PPP/IPCP IP Closed",sp->iface->name);
  787.         if (ipcpiop->active)
  788.             ipcpiop->ipcp_state = IPCP_CLOSED;
  789.         else
  790.             ipcpiop->ipcp_state = IPCP_LISTEN;
  791.         /* Prepare for next open */
  792.         ipcp_reset(sp);
  793.         /* We are done; signal anyone waiting for us to close */
  794.         psignal(ipcpiop,0);
  795.         break;
  796.     case IPCP_REQ_SENT:
  797.         /* Wait for timeout to restart attempt */
  798.         break;
  799.     case IPCP_ACK_SENT:
  800.     case IPCP_ACK_RCVD:
  801.         /* Something went wrong; restart negotiations */
  802.         ipcp_reset(sp);
  803.         ipcp_sendreq(sp);
  804.         break;
  805.     case IPCP_CLOSED:
  806.     case IPCP_LISTEN:
  807.     default:
  808.         /* Unexpected, but no action needed */
  809.         break;
  810.     }
  811.  
  812.     return;
  813. }
  814.  
  815. /* Remote peer requested that we close the IP layer */
  816. static void
  817. ipcp_rcvtermreq(sp, rcnf)
  818. struct slip *sp;
  819. struct cnfhdr *rcnf;
  820. {
  821.     struct pppctl *pppiop;
  822.     struct ipcpctl *ipcpiop;
  823.  
  824.     if (ppptrace > 5)
  825.         mainlog(-1, "ipcp_shutdown()");
  826.  
  827.     pppiop = sp->pppio;
  828.     ipcpiop = &(pppiop->ipcpio);
  829.  
  830.     /* Reset IP connections on this interface */
  831.     ipcp_reset_tcp(sp);
  832.     /* Remove routing entry from route table */
  833.     rt_drop(ipcpiop->attempt_dest, (unsigned int)32);
  834.  
  835.     if (ppptrace)
  836.         mainlog(-1,"%s: PPP/IPCP Peer requested close",sp->iface->name);
  837.     ipcpiop->active = 0;
  838.     ipcpiop->ipcp_state = IPCP_LISTEN;
  839.  
  840.     ipcp_sendreply(sp, TERMINATE_ACK, rcnf->id, NULLBUF);
  841.     ipcp_reset(sp);
  842.     return;
  843. }
  844.  
  845. /* Shutdown the IPCP connection */
  846. static void
  847. ipcp_shutdown(sp)
  848. struct slip *sp;
  849. {
  850.     struct pppctl *pppiop;
  851.     struct ipcpctl *ipcpiop;
  852.  
  853.     if (ppptrace > 5)
  854.         mainlog(-1, "ipcp_shutdown()");
  855.  
  856.     pppiop = sp->pppio;
  857.     ipcpiop = &(pppiop->ipcpio);
  858.  
  859.     /* Reset IP connections on this interface */
  860.     ipcp_reset_tcp(sp);
  861.     /* Remove routing entry from route table */
  862.     rt_drop(ipcpiop->attempt_dest, (unsigned int)32);
  863.  
  864.     if (ppptrace)
  865.         mainlog(-1,"%s: PPP/IPCP IP Shutdown",sp->iface->name);
  866.     if (ipcpiop->active)
  867.         ipcpiop->ipcp_state = IPCP_CLOSED;
  868.     else
  869.         ipcpiop->ipcp_state = IPCP_LISTEN;
  870.  
  871.     ipcp_sendreply(sp,TERMINATE_ACK,0,NULLBUF);
  872.     ipcp_reset(sp);
  873.     return;
  874. }
  875.  
  876. /*******************************************/
  877.  
  878. /* Process configuration ACK send by remote host */
  879. static int
  880. ipcp_chkack(sp, ackcnf, data)
  881. struct slip *sp;
  882. struct cnfhdr *ackcnf;
  883. struct mbuf *data;
  884. {
  885.     int ackerr = 0;
  886.     struct pppctl *pppiop;
  887.     struct ipcpctl *ipcpiop;
  888.     struct mbuf *req_bp;
  889.     struct opthdr reqopt;
  890.     struct opthdr ackopt;
  891.     int16 reqi16, acki16;
  892.     int32 reqsrc_ip, reqdest_ip, acksrc_ip, ackdest_ip;
  893.  
  894.     if (ppptrace > 5)
  895.         mainlog(-1,"ipcp_chkack()");
  896.  
  897.     pppiop = sp->pppio;
  898.     ipcpiop = &(pppiop->ipcpio);
  899.  
  900.     /* IPCP ID field must match last request we sent */
  901.     if (ackcnf->id != ipcpiop->lastid) {
  902.         if (ppptrace > 1)
  903.             mainlog(-1,"improper IPCP ACK; bad ID");
  904.         free_p(data);
  905.         return -1;
  906.     }
  907.  
  908.     /* Get a copy of last request we sent */
  909.     req_bp = ipcp_makereq(ipcpiop);
  910.  
  911.     /* Overall buffer length should match */
  912.     if (ackcnf->len != len_p(req_bp)) {
  913.         ackerr = 1;
  914.     }
  915.  
  916.     /* ACK must echo all options we requested in the order requested */
  917.     while ((ntohopt(&reqopt, &req_bp) != -1) && (!ackerr)) {
  918.         /* Get config option from ACK packet */
  919.         if (ntohopt(&ackopt, &data) == -1) {
  920.             /* Must have as many acked options as requested */
  921.             ackerr = 1;
  922.             break;
  923.         }
  924.  
  925.         /* Config option headers must match */
  926.         if ((ackopt.type != reqopt.type)
  927.            ||(ackopt.len != reqopt.len)) {
  928.             ackerr = 1;
  929.             break;
  930.         }
  931.  
  932.         /* Config option values must match */
  933.         switch(reqopt.type) {
  934.         case IP_ADDRS:        /* IP address */
  935.             /* Echoed values must match our request */
  936.             reqsrc_ip = pull32(&req_bp);
  937.             reqdest_ip = pull32(&req_bp);
  938.             acksrc_ip = pull32(&data);
  939.             ackdest_ip = pull32(&data);
  940.  
  941.             if (acksrc_ip != reqsrc_ip) {
  942.                 ackerr = 1;
  943.                 break;
  944.             }
  945.             if (ackdest_ip != reqdest_ip) {
  946.                 ackerr = 1;
  947.                 break;
  948.             }
  949.             break;
  950.  
  951.         case IP_COMPR_TYPE:    /* IP header compr */
  952.             /* Echoed values must match our request */
  953.             reqi16 = pull16(&req_bp);
  954.             acki16 = pull16(&data);
  955.  
  956.             if (reqi16 != acki16) {
  957.                 ackerr = 1;
  958.                 break;
  959.             }
  960.             break;
  961.         default:        /* Shouldnt happen */
  962.             ackerr = 1;
  963.             break;
  964.         }
  965.     }
  966.  
  967.     free_p(req_bp);
  968.     free_p(data);
  969.  
  970.     if (ackerr) {
  971.         /* Error in configuration ACK */
  972.         if (ppptrace > 5)
  973.             mainlog(-1,"improper IPCP ACK echo");
  974.         return -1;
  975.     }
  976.  
  977.     /* ACK matches last request we made */
  978.     if (ppptrace > 5)
  979.         mainlog(-1,"valid IPCP ACK echo");
  980.     return 0;
  981. }
  982.  
  983. /* Process configuration NAK send by remote host */
  984. static int
  985. ipcp_chknak(sp, nakcnf, data)
  986. struct slip *sp;
  987. struct cnfhdr *nakcnf;
  988. struct mbuf *data;
  989. {
  990.     int nakerr = 0;
  991.     struct pppctl *pppiop;
  992.     struct ipcpctl *ipcpiop;
  993.     struct mbuf *req_bp;
  994.     struct opthdr reqopt;
  995.     struct opthdr nakopt;
  996.     int16 naki16;
  997.     int32 naksrc_ip, nakdest_ip;
  998.  
  999.     if (ppptrace > 5)
  1000.         mainlog(-1,"ipcp_chknak()");
  1001.  
  1002.     pppiop = sp->pppio;
  1003.     ipcpiop = &(pppiop->ipcpio);
  1004.  
  1005.     /* IPCP ID field must match last request we sent */
  1006.     if (nakcnf->id != ipcpiop->lastid) {
  1007.         if (ppptrace > 1)
  1008.             mainlog(-1,"improper IPCP NAK; bad ID");
  1009.         free_p(data);
  1010.         return -1;
  1011.     }
  1012.  
  1013.     /* Get a copy of last request we sent */
  1014.     req_bp = ipcp_makereq(ipcpiop);
  1015.  
  1016.     /* Check overall buffer length */
  1017.     if (nakcnf->len > len_p(req_bp)) {
  1018.         /* Remote cant NAK more options than we requested */
  1019.         nakerr = 1;
  1020.     }
  1021.  
  1022.     /* NAKed options must be same order as our original request */
  1023.     while ((ntohopt(&nakopt, &data) != -1) && (!nakerr)) {
  1024.         /* Get config option from our request */
  1025.         if (ntohopt(&reqopt, &req_bp) == -1) {
  1026.             /* Must find match to each NAKed option */
  1027.             nakerr = 1;
  1028.             break;
  1029.         }
  1030.  
  1031.         /* Maybe not all options were NAKed; look */
  1032.         /* for matching option in our request     */
  1033.         while (reqopt.type != nakopt.type) {
  1034.             /* This option not NAKed; eat rest   */
  1035.             /* of option from the request packet */
  1036.             reqopt.len -= 2;
  1037.             while (reqopt.len--)
  1038.                 pullchar(&req_bp);
  1039.  
  1040.             /* Get next config option from our request */
  1041.             if (ntohopt(&reqopt, &req_bp) == -1) {
  1042.                 /* Must find match to each NAKed option */
  1043.                 reqopt.type = 0;
  1044.                 nakerr = 1;
  1045.                 break;
  1046.             }
  1047.         }
  1048.  
  1049.         /* Config option headers must match */
  1050.         if ((nakopt.type != reqopt.type)
  1051.            ||(nakopt.len != reqopt.len)) {
  1052.             nakerr = 1;
  1053.             break;
  1054.         }
  1055.  
  1056.         /* Remote host replaced our request with new suggestion */
  1057.         switch(reqopt.type) {
  1058.         case IP_ADDRS:        /* IP address */
  1059.             /* Get replacement value from NAK packet */
  1060.             naksrc_ip = pull32(&data);
  1061.             nakdest_ip = pull32(&data);
  1062.             /* Eat option value from our request packet */
  1063.             pull32(&req_bp);
  1064.             pull32(&req_bp);
  1065.  
  1066.             /* Ignore remote if we want to control addrs */
  1067.             if (ipcpiop->accept_addrs != 0) {
  1068.                 /* We asked remote for our addresses */
  1069.                 if (ipcpiop->attempt_src == 0L)
  1070.                     ipcpiop->attempt_src = naksrc_ip;
  1071.                 if (ipcpiop->attempt_dest == 0L)
  1072.                     ipcpiop->attempt_dest = nakdest_ip;
  1073.             }
  1074.             break;
  1075.         case IP_COMPR_TYPE:    /* IP header compr */
  1076.             /* Get replacement value from NAK packet */
  1077.             naki16 = pull16(&data);
  1078.             /* Eat option value from our request packet */
  1079.             pull16(&req_bp);
  1080.  
  1081.             /* See if we can do this type of IP compression */
  1082.             switch (naki16) {
  1083.             /* Ask for Van Jacobson TCP compression */
  1084.             case IPCP_OVJCOMP:
  1085.                 ipcpiop->lcl_ip_compr = IPCP_OVJCOMP;
  1086.                 break;
  1087.             case IPCP_NVJCOMP:
  1088.                 ipcpiop->lcl_ip_compr = IPCP_NVJCOMP;
  1089.                 break;
  1090.             default:
  1091.             /* Cant do that type of compr, ask for none */
  1092.                 ipcpiop->lcl_ip_compr = DEF_IP_COMPR;
  1093.             }
  1094.             break;
  1095.         default:        /* Shouldnt happen */
  1096.             nakerr = 1;
  1097.             break;
  1098.         }
  1099.     }
  1100.  
  1101.     free_p(req_bp);
  1102.     free_p(data);
  1103.  
  1104.     if (nakerr) {
  1105.         /* Error in configuration NAK */
  1106.         if (ppptrace > 5)
  1107.             mainlog(-1,"improper IPCP NAK echo");
  1108.         return -1;
  1109.     }
  1110.  
  1111.     /* NAK matches last request we made */
  1112.     if (ppptrace > 5)
  1113.         mainlog(-1,"valid IPCP NAK echo");
  1114.     return 0;
  1115. }
  1116.  
  1117. /* Process configuration reject send by remote host */
  1118. static int
  1119. ipcp_chkrej(sp, rejcnf, data)
  1120. struct slip *sp;
  1121. struct cnfhdr *rejcnf;
  1122. struct mbuf *data;
  1123. {
  1124.     int rejerr = 0;
  1125.     struct pppctl *pppiop;
  1126.     struct ipcpctl *ipcpiop;
  1127.     struct mbuf *req_bp;
  1128.     struct opthdr reqopt;
  1129.     struct opthdr rejopt;
  1130.  
  1131.     if (ppptrace > 5)
  1132.         mainlog(-1,"ipcp_chkrej()");
  1133.  
  1134.     pppiop = sp->pppio;
  1135.     ipcpiop = &(pppiop->ipcpio);
  1136.  
  1137.     /* IPCP ID field must match last request we sent */
  1138.     if (rejcnf->id != ipcpiop->lastid) {
  1139.         if (ppptrace > 1)
  1140.             mainlog(-1,"improper IPCP REJ; bad ID");
  1141.         free_p(data);
  1142.         return -1;
  1143.     }
  1144.  
  1145.     /* Get a copy of last request we sent */
  1146.     req_bp = ipcp_makereq(ipcpiop);
  1147.  
  1148.     /* Check overall buffer length */
  1149.     if (rejcnf->len > len_p(req_bp)) {
  1150.         /* Remote cant NAK more options than we requested */
  1151.         rejerr = 1;
  1152.     }
  1153.  
  1154.     /* Rejected options must be same order as our original request */
  1155.     while ((ntohopt(&rejopt, &data) != -1) && (!rejerr)) {
  1156.         /* Get config option from our request */
  1157.         if (ntohopt(&reqopt, &req_bp) == -1) {
  1158.             /* Must find match to each NAKed option */
  1159.             rejerr = 1;
  1160.             break;
  1161.         }
  1162.  
  1163.         /* Maybe not all options were NAKed; look */
  1164.         /* for matching option in our request     */
  1165.         while (reqopt.type != rejopt.type) {
  1166.             /* This option not NAKed; eat rest   */
  1167.             /* of option from the request packet */
  1168.             reqopt.len -= 2;
  1169.             while (reqopt.len--)
  1170.                 pullchar(&req_bp);
  1171.  
  1172.             /* Get next config option from our request */
  1173.             if (ntohopt(&reqopt, &req_bp) == -1) {
  1174.                 /* Must find match to each NAKed option */
  1175.                 reqopt.type = 0;
  1176.                 rejerr = 1;
  1177.                 break;
  1178.             }
  1179.         }
  1180.  
  1181.         /* Config option headers must match */
  1182.         if ((rejopt.type != reqopt.type)
  1183.            ||(rejopt.len != reqopt.len)) {
  1184.             rejerr = 1;
  1185.             break;
  1186.         }
  1187.  
  1188.         /* Remote host wont negotiate this option */
  1189.         switch(reqopt.type) {
  1190.         case IP_ADDRS:        /* IP address */
  1191.             /* Eat option values from each packet */
  1192.             pull32(&req_bp);
  1193.             pull32(&req_bp);
  1194.             pull32(&data);
  1195.             pull32(&data);
  1196.  
  1197.             /* Abandon attempt to negotiate IP addrs */
  1198.             ipcpiop->attempt_addrs = 0;
  1199.             break;
  1200.         case IP_COMPR_TYPE:    /* IP header compression */
  1201.             /* Eat option values from each packet */
  1202.             pull16(&req_bp);
  1203.             pull16(&data);
  1204.  
  1205.             /* Abandon attempt to negotiate IP compression */
  1206.             ipcpiop->attempt_ip_compr = 0;
  1207.             ipcpiop->lcl_ip_compr = DEF_IP_COMPR;
  1208.             break;
  1209.         default:        /* Shouldnt happen */
  1210.             rejerr = 1;
  1211.             break;
  1212.         }
  1213.     }
  1214.  
  1215.     free_p(req_bp);
  1216.     free_p(data);
  1217.  
  1218.     if (rejerr) {
  1219.         /* Error in configuration reject */
  1220.         if (ppptrace > 5)
  1221.             mainlog(-1,"improper IPCP REJ echo");
  1222.         return -1;
  1223.     }
  1224.  
  1225.     /* Reject matches last request we made */
  1226.     if (ppptrace > 5)
  1227.         mainlog(-1,"valid IPCP REJ echo");
  1228.     return 0;
  1229. }
  1230.  
  1231. /* Check IP Control options requested by the remote host */
  1232. static void
  1233. ipcp_chkreq(sp, reqcnf, data)
  1234. struct slip *sp;
  1235. struct cnfhdr *reqcnf;
  1236. struct mbuf *data;
  1237. {
  1238.     struct pppctl *pppiop;
  1239.     struct ipcpctl *ipcpiop;
  1240.     int ilen;
  1241.     int16 i16;
  1242.     int32 reqsrc_ip, reqdest_ip;
  1243.     register unsigned char *cp;
  1244.     char cnf_accept = CONFIG_ACK;        /* Overall reply to request */
  1245.     char opt_accept;            /* Per option reply */
  1246.     struct opthdr reqopt;            /* Per option header storage */
  1247.     struct opthdr replyopt;            /* For building reply */
  1248.     struct mbuf *bp;            /* Ptr for building reply */
  1249.     struct mbuf *reply_bp = NULLBUF;    /* Actual reply packet */
  1250.  
  1251.     if (ppptrace > 5)
  1252.         mainlog(-1, "ipcp_chkreq()");
  1253.  
  1254.     pppiop = sp->pppio;
  1255.     ipcpiop = &(pppiop->ipcpio);
  1256.  
  1257.     /* Make sure length in IPCP config header is realistic */
  1258.     ilen = len_p(data);
  1259.     if (ilen < reqcnf->len)
  1260.         reqcnf->len = ilen;
  1261.  
  1262.     /* Process options requested by remote host */
  1263.     while (reqcnf->len > 0) {
  1264.         /* Get header for next option */
  1265.         if (ntohopt(&reqopt, &data) == -1)
  1266.             break;
  1267.  
  1268.         reqcnf->len -= reqopt.len;    /* Count bytes this option */
  1269.         reqopt.len -= 2;        /* Get data len this option */
  1270.         opt_accept = CONFIG_ACK;    /* Assume will accept option */
  1271.  
  1272.         switch(reqopt.type) {
  1273.         case IP_ADDRS:        /* IP address */
  1274.             if (ppptrace > 5)
  1275.                 mainlog(-1, "remote asking to negotiate IP addrs");
  1276.  
  1277.             /* IP Addr is 2 32bit fields */
  1278.             ilen = 8;
  1279.             if (reqopt.len < ilen) {
  1280.                 /* Short option data; reject packet */
  1281.                 opt_accept = CONFIG_REJ;
  1282.                 break;
  1283.             }
  1284.  
  1285.             /* Get proposed value from packet */
  1286.             reqsrc_ip = pull32(&data);
  1287.             reqdest_ip = pull32(&data);
  1288.             if (ppptrace > 5) {
  1289.                 mainlog(-1,    "src IP addr: %s",
  1290.                     inet_ntoa(reqsrc_ip));
  1291.                 mainlog(-1,    "dest IP addr: %s",
  1292.                     inet_ntoa(reqdest_ip));
  1293.  
  1294.             }
  1295.  
  1296.             /* Check requested IP addresses */
  1297.             if (ipcpiop->accept_addrs == 0) {
  1298.                 /* Request okay if it matches what we want */
  1299.                 if ((reqsrc_ip == ipcpiop->attempt_dest)
  1300.                     && (reqdest_ip == ipcpiop->attempt_src)) {
  1301.                     opt_accept = CONFIG_ACK;    
  1302.                     /* Save these values for later */
  1303.                     ipcpiop->accept_src = reqsrc_ip;
  1304.                     ipcpiop->accept_dest = reqdest_ip;
  1305.                     break;
  1306.                 }
  1307.                 if ((reqsrc_ip == ipcpiop->accept_src)
  1308.                     && (reqdest_ip == ipcpiop->accept_dest)) {
  1309.                     /* We already NAKed these once */
  1310.                     opt_accept = CONFIG_REJ;
  1311.                     break;
  1312.                 }
  1313.  
  1314.                 /* Cant accept suggestion of remote host */
  1315.                 opt_accept = CONFIG_NAK;
  1316.                 /* Save these values in case remote insists */
  1317.                 ipcpiop->accept_src = reqsrc_ip;
  1318.                 ipcpiop->accept_dest = reqdest_ip;
  1319.                 /* Tell remote what to request instead */
  1320.                 reqsrc_ip = ipcpiop->attempt_dest;
  1321.                 reqdest_ip = ipcpiop->attempt_src;
  1322.                 break;
  1323.             }
  1324.  
  1325.             /* Make sure remote is not repeating itself */
  1326.             if ((reqsrc_ip == ipcpiop->accept_src)
  1327.                 && (reqdest_ip == ipcpiop->accept_dest)) {
  1328.                 /* We already NAKed these once */
  1329.                 opt_accept = CONFIG_REJ;
  1330.                 break;
  1331.             }
  1332.  
  1333.             /* Save these values for later */
  1334.             ipcpiop->accept_src = reqsrc_ip;
  1335.             ipcpiop->accept_dest = reqdest_ip;
  1336.             /* Remote host may request IP addrs */
  1337.             if(reqsrc_ip == 0L) {
  1338.                 /* Remote host request its IP addr */
  1339.                 if (ipcpiop->attempt_dest == 0L) {
  1340.                     /* We dont have an addr for remote */
  1341.                     opt_accept = CONFIG_REJ;
  1342.                     break;
  1343.                 } else {
  1344.                     /* Give IP addr to remote peer */
  1345.                     opt_accept = CONFIG_NAK;
  1346.                     reqsrc_ip = ipcpiop->attempt_dest;
  1347.                 }
  1348.             } else {
  1349.                 /* Remote host gave us its IP addr */
  1350.                 if (ipcpiop->attempt_dest == 0L) {
  1351.                     /* We need to know peer IP addr */
  1352.                     ipcpiop->attempt_dest = reqsrc_ip;
  1353.                 } else {
  1354.                     /* We already know peer IP addr */
  1355.                     if (reqsrc_ip != ipcpiop->attempt_dest) {
  1356.                         opt_accept = CONFIG_NAK;
  1357.                         reqsrc_ip = ipcpiop->attempt_dest;
  1358.                     }
  1359.                 }
  1360.             }
  1361.             if (reqdest_ip == 0L) {
  1362.                 /* Remote host requested our IP addr */
  1363.                 if (ipcpiop->attempt_src == 0L) {
  1364.                     /* We dont know our IP addr */
  1365.                     opt_accept = CONFIG_REJ;
  1366.                     break;
  1367.                 } else {
  1368.                     /* Tell remote what our IP addr is */
  1369.                     opt_accept = CONFIG_NAK;
  1370.                     reqdest_ip = ipcpiop->attempt_src;
  1371.                 }
  1372.             } else {
  1373.                 /* Remote host gave us our IP addr */
  1374.                 if (ipcpiop->attempt_src == 0L) {
  1375.                     /* We need to know our IP addr */
  1376.                     ipcpiop->attempt_src = reqdest_ip;
  1377.                 } else {
  1378.                     /* We already know our IP addr */
  1379.                     if (reqdest_ip != ipcpiop->attempt_src) {
  1380.                         opt_accept = CONFIG_NAK;
  1381.                         reqdest_ip = ipcpiop->attempt_src;
  1382.                     }
  1383.                 }
  1384.             }
  1385.             break;
  1386.  
  1387.         case IP_COMPR_TYPE:    /* IP header compression */
  1388.             if (ppptrace > 5) {
  1389.                 mainlog(-1, "remote asking to negotiate IP compression");
  1390.             }
  1391.  
  1392.             /* IP compression type is a 16 bit field */
  1393.             ilen = 2;
  1394.             if (reqopt.len < ilen) {
  1395.                 /* Short option; reject packet */
  1396.                 opt_accept = CONFIG_REJ;
  1397.                 break;
  1398.             }
  1399.  
  1400.             /* Get proposed value from packet */
  1401.             i16 = pull16(&data);
  1402.             if ((ipcpiop->accept_ip_compr == 0)
  1403.                 && (i16 != DEF_IP_COMPR)) {
  1404.                 /* Not open for negotiation */
  1405.                 opt_accept = CONFIG_REJ;
  1406.                 break;
  1407.             }
  1408.  
  1409.             /* Check if requested compr type is acceptable */
  1410.             switch (i16) {
  1411.             /* We can do Van Jacobson TCP header compr */
  1412.             case IPCP_OVJCOMP:
  1413.                 opt_accept = CONFIG_ACK;
  1414.                 break;
  1415.             case IPCP_NVJCOMP:
  1416.                 opt_accept = CONFIG_ACK;
  1417.                 break;
  1418.             deafult:
  1419.             /* Dont know this compression type; suggest 
  1420.                Van Jacobson TCP header compression (NEW) */
  1421.                 opt_accept = CONFIG_NAK;
  1422.                 i16 = IPCP_NVJCOMP;
  1423.             }
  1424.             ipcpiop->rem_ip_compr = i16;
  1425.             break;
  1426.  
  1427.         default:        /* Unknown option */
  1428.             if (ppptrace > 5)
  1429.                 mainlog(-1,    "remote asking for unimplemented option: %x   len: %d",
  1430.                     reqopt.type, reqopt.len);
  1431.             opt_accept = CONFIG_REJ;
  1432.             ilen = reqopt.len;
  1433.             if (len_p(data) < ilen)
  1434.                 ilen = len_p(data);
  1435.             /* Data dequeued at echo time */
  1436.  
  1437.             break;
  1438.         }
  1439.         if ((opt_accept == CONFIG_ACK) &&
  1440.             (cnf_accept != CONFIG_ACK))
  1441.             /* This option was good, but a previous      */
  1442.             /* option was not. Return only those options */
  1443.             /* which are being nacked/rejected.          */
  1444.             continue;
  1445.  
  1446.         if (opt_accept == CONFIG_NAK) {
  1447.             if (cnf_accept == CONFIG_REJ)
  1448.                 /* Return only those options */
  1449.                 /* which are being rejected. */
  1450.                 continue;
  1451.             if (cnf_accept == CONFIG_ACK) {
  1452.                 /* Discard current list of good options */
  1453.                 free_p(reply_bp);
  1454.                 reply_bp = NULLBUF;
  1455.                 /* Send a list of nacked options */
  1456.                 cnf_accept = CONFIG_NAK;
  1457.             }
  1458.         }
  1459.  
  1460.         if (opt_accept == CONFIG_REJ) {
  1461.             if (cnf_accept != CONFIG_REJ) {
  1462.                 /* Discard current list of good options */
  1463.                 free_p(reply_bp);
  1464.                 reply_bp = NULLBUF;
  1465.                 /* Send a list of rejected options */
  1466.                 cnf_accept = CONFIG_REJ;
  1467.             }
  1468.         }
  1469.  
  1470.         /* Add option response to the return list */
  1471.         replyopt.type = reqopt.type;
  1472.         replyopt.len = ilen + OPT_HDRLEN;
  1473.         if ((bp = htonopt(&replyopt)) == NULLBUF)
  1474.             break;
  1475.         append(&reply_bp,bp);
  1476.         if (ilen) {
  1477.             if ((bp = alloc_mbuf(ilen)) == NULLBUF)
  1478.                 break;
  1479.             cp = bp->data;
  1480.             switch(ilen) {
  1481.             case 2:
  1482.                 put16(cp,i16);
  1483.                 bp->cnt += 2;
  1484.                 break;
  1485.             case 8:
  1486.                 cp = put32(cp, reqsrc_ip);
  1487.                 put32(cp, reqdest_ip);
  1488.                 bp->cnt += 8;
  1489.                 break;
  1490.             default:
  1491.                 while (ilen--)
  1492.                     bp->data[bp->cnt++] = pullchar(&data);
  1493.             }
  1494.             append(&reply_bp,bp);
  1495.         }
  1496.     }
  1497.  
  1498.     /* Send ACK/NAK/REJ to remote host */
  1499.     if (cnf_accept == CONFIG_ACK) {
  1500.         if (ppptrace > 1)
  1501.             mainlog(-1, "accept all options requested by remote peer");
  1502.  
  1503.         /* Accept configuration requested by remote host */
  1504.         ipcp_sendreply(sp, CONFIG_ACK, reqcnf->id, reply_bp);
  1505.         if (ipcpiop->ipcp_state == IPCP_REQ_SENT) {
  1506.             ipcpiop->ipcp_state = IPCP_ACK_SENT;
  1507.         } else {
  1508.             /* PPP data link now ready for IP traffic */
  1509.             ipcp_open(sp);
  1510.         }
  1511.     } else {
  1512.         if (ppptrace > 1)
  1513.             mainlog(-1,"options requested by remote peer not accepted: %s",
  1514.                 ((cnf_accept==CONFIG_NAK) ? "NAK" : "REJ"));
  1515.  
  1516.         /* NAK/REJ config request made by remote host */
  1517.         ipcp_sendreply(sp, cnf_accept, reqcnf->id, reply_bp);
  1518.  
  1519.         /* Start timer against wait for amended config request */
  1520.         if (ipcpiop->ipcp_state == IPCP_ACK_RCVD)
  1521.             ipcp_timer(sp);
  1522.     }
  1523.     free_p(data);
  1524.     return;
  1525. }
  1526.  
  1527. /****************************************************************************/
  1528.  
  1529. /* Timeout while waiting for reply from remote host */
  1530. static void
  1531. ipcp_timeout(vp)
  1532. void *vp;
  1533. {
  1534.     struct slip *sp;
  1535.     struct pppctl *pppiop;
  1536.     struct ipcpctl *ipcpiop;
  1537.  
  1538.     if (ppptrace > 1)
  1539.         mainlog(-1, "ipcp_timeout()");
  1540.  
  1541.     /* Load pointers to interface that timed-out */
  1542.     sp = (struct slip *)vp;
  1543.     pppiop = sp->pppio;
  1544.     ipcpiop = &(pppiop->ipcpio);
  1545.  
  1546.     /* Attempt to get things going again */
  1547.     switch(ipcpiop->ipcp_state) {
  1548.     case IPCP_ACK_SENT:
  1549.         /* Remote host isnt listening to our request */
  1550.         ipcp_reset(sp);
  1551.     case IPCP_REQ_SENT:
  1552.     case IPCP_ACK_RCVD:
  1553.         if (!ipcpiop->active) {
  1554.             /* If passive open, we got a CONFIG_REQ from remote */
  1555.             /* host but no ACK in response to our CONFIG_REQ    */
  1556.             if (++ipcpiop->ack_retry > IPCP_RETRY_MAX) {
  1557.                 /* Remote host doesnt seem to be listening */
  1558.                 ipcp_shutdown(sp);
  1559.                 break;
  1560.             }
  1561.         }
  1562.         /* Timeout waiting for ACK to our request,         */
  1563.         /* or timeout waiting for request from remote host */
  1564.         ipcp_sendreq(sp);
  1565.         break;
  1566.  
  1567.     case IPCP_TERMINATE:
  1568.         /* Timeout waiting for terminate ACK; send another request */
  1569.         if (++ipcpiop->ack_retry > IPCP_TERM_RETRY) {
  1570.             /* No response to our polite request; give it up */
  1571.             if (ppptrace)
  1572.                 mainlog(-1,"%s: PPP/IPCP IP Closed without reply from remote peer",sp->iface->name);
  1573.             if (ipcpiop->active)
  1574.                 ipcpiop->ipcp_state = IPCP_CLOSED;
  1575.             else
  1576.                 ipcpiop->ipcp_state = IPCP_LISTEN;
  1577.  
  1578.             ipcp_sendreply(sp,TERMINATE_ACK,0,NULLBUF);
  1579.             ipcp_reset(sp);
  1580.             tprintf("Still no response; marking IPCP layer as closed\n");
  1581.             psignal(ipcpiop,0);
  1582.         } else {
  1583.             /* Request remote host to close IP */
  1584.             tprintf("Timeout waiting for response to our IPCP terminate request\n");
  1585.             ipcp_timer(sp);
  1586.             ipcp_sendreply(sp, TERMINATE_REQ, 0, NULLBUF);
  1587.         }
  1588.         break;
  1589.  
  1590.     case IPCP_CLOSED:
  1591.     case IPCP_LISTEN:
  1592.     case IPCP_OPEN:
  1593.     default:
  1594.         /* Confusion; shutdown the connection */
  1595.         ipcp_shutdown(sp);
  1596.         break;
  1597.     }
  1598.     return;
  1599. }
  1600.  
  1601. /* Set a timer in case an expected event does not occur */
  1602. static void
  1603. ipcp_timer(sp)
  1604. struct slip *sp;
  1605. {
  1606.     struct pppctl *pppiop;
  1607.     struct ipcpctl *ipcpiop;
  1608.     struct timer *t;
  1609.  
  1610.     if (ppptrace > 5)
  1611.         mainlog(-1,"ipcp_timer()");
  1612.  
  1613.     pppiop = sp->pppio;
  1614.     ipcpiop = &(pppiop->ipcpio);
  1615.     t = &(ipcpiop->ipcp_tm);
  1616.     t->func = (void (*)())ipcp_timeout;
  1617.     t->arg = (void *)sp;
  1618.     start_timer(t);
  1619.     return;
  1620. }
  1621.  
  1622. /****************************************************************************/
  1623.  
  1624. /* Send an IPCP packet to the remote host */
  1625. static int
  1626. ipcp_sendreply(sp,code,id,data)
  1627. struct slip *sp;
  1628. char code;
  1629. unsigned char id;
  1630. struct mbuf *data;
  1631. {
  1632.     struct iface *iface;
  1633.     struct cnfhdr hdr;
  1634.  
  1635.     /* Load IPCP header values */
  1636.     hdr.code = code;
  1637.     switch(code) {
  1638.     case CONFIG_REQ:
  1639.     case TERMINATE_REQ:
  1640.         /* Save ID field for match aginst replies from remote host */
  1641.         sp->pppio->ipcpio.lastid = pppid;
  1642.         /* Use a unique ID field value */
  1643.         hdr.id = pppid++;
  1644.         break;
  1645.  
  1646.     case CONFIG_ACK:
  1647.     case CONFIG_NAK:
  1648.     case CONFIG_REJ:
  1649.     case TERMINATE_ACK:
  1650.     case CODE_REJ:
  1651.         /* Use ID sent by remote host */
  1652.         hdr.id = id;
  1653.         break;
  1654.  
  1655.     default:
  1656.         /* Shouldnt happen */
  1657.         if (ppptrace)
  1658.             mainlog(-1, "bogus code: %x\n", code);
  1659.         return -1;
  1660.     }
  1661.     hdr.len = len_p(data) + CNF_HDRLEN;
  1662.  
  1663.     /* Prepend IPCP header to packet data */
  1664.     if ((data = htoncnf(&hdr,data)) == NULLBUF)
  1665.         return -1;
  1666.  
  1667.     if (ppptrace > 1)
  1668.         mainlog(-1, "%s: PPP/IPCP Send: current state: %s   IPCP option: %s  id: %d  len: %d",
  1669.             sp->iface->name,
  1670.             LCPStates[sp->pppio->ipcpio.ipcp_state],
  1671.             LCPCodes[code],hdr.id,hdr.len);
  1672.  
  1673.     /* Send IPCP packet to remote host */
  1674.     sp->pppio->sndipcp++;
  1675.     iface = sp->iface;
  1676.     return( (*iface->output)
  1677.         (iface, NULLCHAR, NULLCHAR, PPP_IPCP_TYPE, data) );
  1678. }
  1679.  
  1680. /* Process incoming IPCP packet */
  1681. void
  1682. ipcpproc(iface,bp)
  1683. struct iface *iface;
  1684. struct mbuf *bp;
  1685. {
  1686.     struct slip *sp;
  1687.     struct cnfhdr hdr;
  1688.  
  1689.     sp = &Slip[iface->xdev];
  1690.  
  1691.     /* Extract IPCP header */
  1692.     ntohcnf(&hdr, &bp);
  1693.     hdr.len -= CNF_HDRLEN;            /* Length includes envelope */
  1694.     trim_mbuf(&bp, hdr.len);        /* Trim off FCS bytes */
  1695.  
  1696.     if (ppptrace > 1)
  1697.         mainlog(-1,    "%s: PPP/IPCP Recv: current state: %s   IPCP option: %s    id: %d   len: %d",
  1698.             iface->name,
  1699.             LCPStates[sp->pppio->ipcpio.ipcp_state],
  1700.             LCPCodes[hdr.code], hdr.id, hdr.len);
  1701.  
  1702.     /* Process IPCP packet data */
  1703.     switch(hdr.code) {
  1704.     case CONFIG_REQ:            /* Request of remote host */
  1705.         ipcp_rcvreq(sp, &hdr, bp);
  1706.         break;
  1707.     case CONFIG_ACK:            /* Remote accepted our req */
  1708.         ipcp_rcvack(sp, &hdr, bp);
  1709.         break;
  1710.     case CONFIG_NAK:            /* Remote adjusted our req */
  1711.         ipcp_rcvnak(sp, &hdr, bp);
  1712.         break;
  1713.     case CONFIG_REJ:            /* Remote rejected our req */
  1714.         ipcp_rcvrej(sp, &hdr, bp);
  1715.         break;
  1716.     case TERMINATE_REQ:            /* Remote request to close */
  1717.         ipcp_rcvtermreq(sp, &hdr);
  1718.         break;
  1719.     case TERMINATE_ACK:            /* Remote closed on request */
  1720.         ipcp_rcvtermack(sp);
  1721.         break;
  1722.  
  1723.     case CODE_REJ:
  1724.         if (ppptrace)
  1725.             mainlog(-1,"Unimplemented IPCP packet type: %x; dropping packet",hdr.code);
  1726.         free_p(bp);
  1727.         break;
  1728.     default:
  1729.         if (ppptrace)
  1730.             mainlog(-1,"Unknown IPCP packet type: %x; dropping packet",hdr.code);
  1731.         free_p(bp);
  1732.         break;
  1733.     }
  1734.     return;
  1735. }
  1736.